﻿using System;
// 动态绑定是将绑定（解析类型、成员和操作的过程）从编译时延迟到运行时。
// 在编译时，如果程序员知道某个特定函数、成员或操作的存在，而编译器还不知道，那么动态绑定是很有用的。
// 这种情况通常出现在操作动态语言（如IronPython）和COM时，而且如果不使用动态绑定，就只能使用反射机制。

// 动态类型是通过上下文关键字dynamic声明的：
//dynamic d = GetSomeObject();
//d.Quack();

//动态绑定类型会告诉编译器“不要紧张”。我们认为d的运行时类型具有一个Quack方法。
//但是我们无法静态地证明这一点。由于d时动态的，所以编译器推迟到运行时才将Quack绑定给d。
//为了真正理解这个概念，我们需要先区分静态绑定和动态绑定。


//4.11.1 静态绑定与动态绑定
// 典型的绑定例子就是在编译表达式时将一个名称映射到一个具体的函数上。
//如果要编译以下表达式，那么编译器需要找到Quack方法的实现：
//d.Quack();
//假设d的静态类型为Duck：
//Duck d = ...
//d.Quack();
//最简单的情况是，编译器查找到Duck中无参数的Quack方法进行绑定。
//如果绑定失败，编译器会将搜索范围扩大到具有可选参数的方法，Duck的基类的方法和将Duck作为其第一个参数的扩展方法。
//如果还是没有找到匹配的方法，那么程序将出现一个编译错误。
//无论绑定的是什么样的方法，其底线是已知绑定是由编译器实现的，而且绑定是完全依赖于已经知道的操作数类型（在这里是d）。这就是所谓的静态绑定。

//现在将 d 的静态类型改为 object：
//object d = ...
//d.Quack();
//调用Quack时，我们会遇到一个编译错误，因为虽然存储在d中的值包含了一个名为Quack的方法，但是只有所包含信息为变量类型时编译器才知道方法的存在，而这里的类型时object。
//现在，将d的静态类型改为dynamic：
//dynamic d = ...
//d.Quack();
//动态类型类似于object，同样不表现为一种类型。其区别是能够在编译时在不知道它存在的情况下使用它。
//动态对象时基于其运行时类型进行绑定的，而不是基于编译时类型。
//当编译器遇到一个动态绑定表达式时（通常是一个包含任意动态类型值的表达式），它仅仅对表达式进行打包，而绑定则在后面的运行时执行。

//在运行时，如果一个动态对象实现了IDynamicMetaObjectProvider，那么这个接口将用来执行绑定。
//否则，绑定的发生方式就几乎像是编译器已经事先知道动态对象的运行时类型一样。
//我们将这两种方式称为自定义绑定和语言绑定。

namespace _129_动态绑定
{
    class Program
    {
        static void Main(string[] args)
        {
            /*
            dynamic d = GetSomeObject();
            d.Quack();
            */

            /*
            object d = GetSomeObject();
            d.Quack();
            */
        }
    }
}
